;
;  PROGRAM:  TEMPLATE
;  VERSION:  1.0
;  DATE:  15 Jan 83
;  AUTHOR:  RICHARD CONN
;  PREVIOUS VERSIONS:  None
;
VERS	equ	10

;
;	TEMPLATE provides a basic template from which to build utilities
; for ZCPR2.  The areas in the TEMPLATE which begin with **** are those
; which must be customized for the specific utility.
;


;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;

FALSE	EQU	0
TRUE	EQU	NOT FALSE

;
;  BASIC SYSLIB ROUTINES NEEDED BY TEMPLATE
;
ESIZE	EQU	16	; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE)

	EXT	DIRFS	; DIRECTORY PROCESSOR
	EXT	DIRPACK	; PACK DIRECTORY

	EXT	ZGPINS	; INIT BUFFERS
	EXT	ZFNAME	; FILE NAME PROCESSOR

	EXT	INITFCB	; INIT FCB
	EXT	BDOS	; BDOS ENTRY
	EXT	RETUD	; RETURN CURRENT USER/DISK
	EXT	PUTUD	; SAVE CURRENT USER/DISK
	EXT	GETUD	; RESTORE CURRENT USER/DISK
	EXT	LOGUD	; LOG INTO USER/DISK
	EXT	PRINT	; PRINT STRING PTED TO BY RET ADR
	EXT	COUT	; CONSOLE OUTPUT ROUTINE
	EXT	CIN	; CONSOLE INPUT ROUTINE
	EXT	CAPS	; CAPITALIZE ROUTINE
	EXT	CRLF	; NEW LINE ROUTINE
	EXT	CLINE	; COMMAND LINE STRING SAVE ROUTINE
	EXT	CODEND	; CODE END COMPUTATION ROUTINE

;
;  CP/M EQUATES
;
CPM	EQU	0	; WARM BOOT
BDOSE	EQU	CPM+5	; BDOS ENTRY
FCB	EQU	CPM+5CH	; FCB
TBUFF	EQU	CPM+80H	; INPUT LINE BUFFER
CR	EQU	13	; <CR>
LF	EQU	10	; <LF>
CTRLC	EQU	3	; ^C

;
;  Branch to Start of Program
;
	JMP	START

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	0FFH	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	0FFH	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	0FFH	; CURRENT INDIC AND DMA?
NDREQD:
	DB	0FFH	; NAMED DIRECTORIES?
Z2CLASS:
	DB	0	; CLASS 0
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  **** Special Initial Value Area for GENINS
;

;
;  Start of Program
;
START:
	LXI	H,0	; GET STACK PTR
	DAD	SP
	SHLD	STACK	; SAVE IT
	LXI	SP,STACK	; SET SP
	CALL	PUTUD	; SAVE CURRENT USER/DISK AWAY
	CALL	RETUD	; GET CURRENT USER/DISK
	MOV	A,B	; SAVE DISK
	STA	DISK
	MOV	A,C	; SAVE USER
	STA	USER

	CALL	ZGPINS	; INIT BUFFERS

	LXI	H,TBUFF	; SAVE COMMAND LINE
	CALL	CLINE
	SHLD	CMDLNE	; SAVE PTR

;
;  **** Banner of Program
;
	CALL	PRINT
	DB	'TEMPLATE  Version '
	DB	VERS/10+'0','.',(VERS MOD 10)+'0',0

;
;  Check for Help Request
;
	LDA	FCB+1	; GET FIRST CHAR OF FILE NAME
	CPI	' '	; NO FILE SPEC?
	JZ	HELP
	CPI	'/'	; OPTION CAUGHT?
	JNZ	ECONT

;
;  **** Print Help Information
;
HELP:
	CALL	PRINT
	DB	CR,LF,'TEMPLATE Command --'
	DB	CR,LF,0

;
;  RETURN TO OS
;
RETURN:
	LHLD	STACK	; GET OLD STACK
	SPHL		; SET IT
	RET

;  EXTRACT FLAGS IF PRESENT
ECONT:
	LXI	H,0	; SET FILE COUNT
	SHLD	FILECNT
	LHLD	CMDLNE	; PT TO BUFFER
;
;  SKIP TO FILE NAME STRING
;
	CALL	SBLANK	; SKIP OVER BLANKS
;
;  SKIP TO END OF FILE NAME STRING
;
	CALL	SNBLANK	; SKIP OVER NON-BLANKS
;
;  CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO
;
OPT:
	CPI	'/'	; OPTION CHAR?
	JNZ	OPTION
	INX	H	; SKIP SLASH
;
;  PROCESS LIST OF OPTIONS
;
OPTION:
	MOV	A,M	; GET BYTE
	ORA	A	; DONE?
	JZ	DSPEC
	INX	H	; PT TO NEXT CHAR
	CPI	' '	; SKIP OVER SPACES
	JZ	OPTION
	MOV	C,A	; COMMAND IN C
	LXI	D,OPTAB	; PT TO OPTION TABLE
OPTL:
	LDAX	D	; GET OPTION LETTER
	ORA	A	; END OF TABLE?
	JZ	HELP	; HELP IF SO
	CMP	C	; MATCH?
	JZ	OPTM	; PROCESS IF SO
	INX	D	; PT TO NEXT ENTRY
	INX	D
	INX	D
	JMP	OPTL
;
;  PROCESS OPTION
;
OPTM:
	PUSH	H	; SAVE HL ON STACK
	LXI	H,OPTION	; GET RETURN ADDRESS
	XTHL		; ... ON STACK AND RESTORE HL
	INX	D	; PT TO ADDRESS
	LDAX	D	; GET ADDRESS LOW
	MOV	B,A	; ... IN B
	INX	D
	LDAX	D	; GET ADDRESS HIGH
	MOV	D,A	; ... IN D
	MOV	E,B	; LOW IN E
	PUSH	D	; PUT ADDRESS ON STACK
	RET		; "CALL" OPTION ROUTINE

;
;  **** OPTION TABLE
;	EACH OPTION IS A CAPITAL LETTER OR SPECIAL CHAR FOLLOWED BY
;		AN ADDRESS; THE TABLE IS TERMINATED BY A BINARY ZERO
;
OPTAB:
	DB	0	; END OF TABLE

;
;  BEGIN MOVING THROUGH FILE NAMES, SEPARATED BY COMMAS
;
DSPEC:
	LHLD	CMDLNE	; PT TO FIRST BYTE
	CALL	SBLANK	; SKIP TO NON-BLANK
;
;  MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS
;    HL PTS TO FIRST BYTE OF NEXT FILE SPEC
;
DSPEC1:
	CALL	GETUD	; RESET USER IF NECESSARY
	LXI	D,NTFCB	; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL

	CALL	ZFNAME	; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER
	JZ	DERR	; ERROR HANDLER

	SHLD	NEXTCH	; SAVE PTR TO DELIMITER WHICH ENDED SCAN
	MOV	A,B	; SAVE POSSIBLE DRIVE SPEC
	CPI	0FFH	; CURRENT DISK?
	JZ	DSPEC2
	LDA	MDISK	; GET MAX DISK NUMBER
	DCR	B	; ADJUST TO WITHIN BOUNDS 0-15
	CMP	B	; WITHIN BOUNDS?
	MOV	A,B	; GET DISK NUMBER IN A
	JNC	USPEC
DERR:
	CALL	PRINT
	DB	CR,LF,'Invalid Disk Specification',0
	JMP	DRETURN

;
;  SET CURRENT DISK
;
DSPEC2:
	LDA	DISK	;GET CURRENT DISK
	MOV	B,A	;... IN B

;  CHECK FOR USER NUMBER
USPEC:
	MOV	A,C	; GET NEW USER NUMBER
	CPI	0FFH	; DEFAULT USER?
	JZ	USPEC1
	CPI	'?'	; ALL USERS NOT ALLOWED?
	JZ	UERR
	LDA	MUSER	; GET MAX USER NUMBER
	CMP	C
	MOV	A,C	; USER NUMBER IN A
	JNC	FCT
UERR:
	CALL	PRINT
	DB	CR,LF,'Invalid User Number',0
	JMP	DRETURN
USPEC1:
	LDA	USER	;GET CURRENT USER
	MOV	C,A	;... IN C

;
;  LOAD DIRECTORY AND PERFORM FUNCTION
;
FCT:
	MOV	A,B	; SAVE NEW DISK/USER AWAY
	STA	CDISK	; CURRENT DISK
	MOV	A,C
	STA	CUSER	; CURRENT USER
	CALL	LOGUD	; LOG INTO ACCOUNT
	CALL	CODEND	; PT TO END OF CODE
	CALL	RETUD	; GET USER NUMBER FOR DIRFS
	MVI	A,11000000B	; SELECT SYS AND NON-SYS FILES
	ORA	C	; OR IN USER NUMBER
	LXI	D,NTFCB	; PT TO FCB
	CALL	INITFCB	; INIT THE FCB
	CALL	DIRFS	; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE
	CALL	ICHECK	; CHECK FOR INSPECT OPTION AND INSPECT IF SET
	CALL	GETUD	; RETURN TO BASE USER/DISK

;
;  PERFORM FUNCTION; HL PTS TO FILE AND BC CONTAINS NUMBER OF FILES
;
FCTL:
	MOV	A,B		; CHECK FOR COMPLETION (COUNT = 0)
	ORA	C
	JZ	FCTL1
	DCX	B		; COUNT DOWN
	PUSH	H		; SAVE PTR AND COUNT
	PUSH	B
	CALL	FUNCTION	; PERFORM FUNCTION
	POP	B		; GET COUNT AND PTR
	POP	H
	LXI	D,ESIZE		; PT TO NEXT ENTRY
	DAD	D
	JMP	FCTL

;
;  CHECK FOR NEXT FILE SPEC
;
FCTL1:
	LHLD	NEXTCH	; GET PTR
	MOV	A,M	; GET DELIM
	CPI	','	; ANOTHER FILE?
	JNZ	DRETURN
	INX	H	; PT TO CHAR AFTER COMMA
	JMP	DSPEC1	; CONTINUE PROCESSING

;
;  **** EMERGENCY ABORT
;
ABORT:
	CALL	PRINT
	DB	CR,LF,'** TEMPLATE Abort **',CR,LF,0
	CALL	GETUD	; RETURN HOME AND FALL THRU TO DRETURN
;
;  **** FUNCTION COMPLETE -- CLEANUP AND EXIT
;	FILL THIS IN WITH CLEANUP CODE FOR EXIT
;
DRETURN:
	JMP	RETURN

;
;  **** INSPECT FILES -- THIS ROUTINE IS TO PERFORM A FILE INSPECTION
;	ON INPUT, HL PTS TO FIRST 16-BYTE ENTRY AND BC=NUMBER OF ENTRIES
;
ICHECK:
	RET

;
;  **** FUNCTION -- MAIN FUNCTION OF TEMPLATE
;	ON ENTRY, HL PTS TO NAME OF FILE (16 BYTES) AND USER IS LOGGED INTO
;		DIRECTORY CONTAINING INDICATED FILE
;
FUNCTION:
	CALL	PRFN	; FOR TEMPLATE
	RET

;
;  UTILITIES
;	SBLANK  -- SKIP BLANKS PTED TO BY HL UNTIL NON-BLANK ENCOUNTERED; HL
;	SNBLANK -- SKIP NON-BLANKS PTED TO BY HL UNTIL BLANK OR EOL; HL
;	PRFN    -- PRINT FILE NAME PTED TO BY HL; AFFECT NOTHING
;

;
;  SKIP UNTIL NON-BLANK
;
SBLANK:
	MOV	A,M	; LOOK FOR BLANK
	INX	H	; PT TO NEXT
	CPI	' '	; BLANK?
	JZ	SBLANK
	DCX	H	; BACK UP
	RET

;
;  SKIP UNTIL BLANK OR EOL
;
SNBLANK:
	MOV	A,M	; GET CHAR
	INX	H	; PT TO NEXT
	CPI	' '	; BLANK?
	JZ	SNB1
	ORA	A	; EOL?
	JNZ	SNBLANK
SNB1:
	DCX	H	; BACK UP
	RET

;
;  PRINT FILE NAME PTED TO BY HL
;	OUTPUT TO CON:
;
PRFN:
	PUSH	H	; SAVE REGS
	PUSH	B
	INX	H	; PT TO FILE NAME
	MVI	B,8	; PRINT NAME
	CALL	PRNT
	MVI	A,'.'	; DECIMAL
	CALL	COUT
	MVI	B,3	; PRINT TYPE
	CALL	PRNT
	POP	B	; GET REGS
	POP	H
	RET

;
;  PRINT CHARS PTED TO BY HL FOR B BYTES
;	OUTPUT TO CON:
;
PRNT:
	MOV	A,M	; GET CHAR
	CALL	COUT
	INX	H	; PT TO NEXT
	DCR	B	; COUNT DOWN
	JNZ	PRNT
	RET

;
;  BUFFERS
;
DISK:
	DS	1	; HOME DISK NUMBER
USER:
	DS	1	; HOME USER NUMBER
CDISK:
	DS	1	; CURRENT DISK NUMBER
CUSER:
	DS	1	; CURRENT USER NUMBER
CMDLNE:
	DS	2	; PTR TO COMMAND LINE STRING
NEXTCH:
	DS	2	; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE
FILECNT:
	DS	2	; COUNT OF NUMBER OF FILES RENAMED
NTFCB:
	DS	36	; FCB FOR NEW FILE
	DS	100	; STACK AREA
STACK:
	DS	2	; OLD STACK PTR

	END
